
/**
\file
Definition of the nmn::logger class.
\author Sean Tromans
*/

#include <boost/thread.hpp>
#include <boost/config.hpp>
#include <fstream>

#if	defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4127)
#pragma warning(disable:4100)
#endif

#include <boost/date_time.hpp>

#if	defined(BOOST_MSVC)
#pragma warning(pop)
#endif

namespace nmn
{

	namespace detail
	{

		/**
		Helper function to construct the formatted string to use for logging.
		@param message The unformatted message string.
		@return The formatted string to output.
		\author Sean Tromans
		*/
		template < typename char_t, typename traits_t, typename allocator_t >
		typename std::basic_string< char_t, traits_t, allocator_t > formatted_string( typename std::basic_string< char_t, traits_t, allocator_t > const & message )
		{
			static_assert( false, "Unsupported character type." );
		}

		template < typename traits_t, typename allocator_t >
		typename std::basic_string< char, traits_t, allocator_t > formatted_string( typename std::basic_string< char, traits_t, allocator_t > const & message )
		{
			return nmn::create_string( "[%1% | %2%]: %3%", boost::posix_time::second_clock::local_time( ), boost::this_thread::get_id( ), message );
		}

		template < typename traits_t, typename allocator_t >
		typename std::basic_string< wchar_t, traits_t, allocator_t > formatted_string( typename std::basic_string< wchar_t, traits_t, allocator_t > const & message )
		{
			return nmn::create_string( L"[%1% | %2%]: %3%", boost::posix_time::second_clock::local_time( ), boost::this_thread::get_id( ), message );
		}
	}

	/**
	Register a log handler with the logger.
	@param The new log handler to process log output.
	@return A connection to the internal signal.
	\author Sean Tromans
	*/
	template< typename char_t, typename traits_t, typename allocator_t >
	typename logger< char_t, traits_t, allocator_t >::signal_connection_type logger< char_t, traits_t, allocator_t >::register_handler( typename handler_signal_type::slot_type const & handler )
	{
		return handler_signal.connect( handler );
	}

	/**
	Outputs a string to the log file.
	@param message The message to output to the log.
	\author Sean Tromans
	*/
	template< typename char_t, typename traits_t, typename allocator_t >
	void logger< char_t, traits_t, allocator_t >::operator( )( typename logger< char_t, traits_t, allocator_t >::char_type const * const message )
	{
		operator( )( string_type( message ) );
	}

	/**
	Outputs a string to the log file.
	@param message The message to output to the log.
	\author Sean Tromans
	*/
	template< typename char_t, typename traits_t, typename allocator_t >
	void logger< char_t, traits_t, allocator_t >::operator( )( typename logger< char_t, traits_t, allocator_t >::string_type const & message )
	{
		boost::mutex::scoped_lock lock( mutex );

		handler_signal( message, detail::formatted_string( message ) );
	}
}
